package pl.gettoknowme.mobile.android.services.sms;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import pl.gettoknowme.mobile.android.services.sms.SmsMessage.MessageType;
import pl.gettoknowme.mobile.android.util.MiscUtils;

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;

/**
 * Czytnik SMS-ów zapisanych w skrzynce.
 * @author Michał Kołodziejski
 */
public class SmsReader {
    public static final Uri SMS_INBOX_CONTENT_URI = Uri.parse("content://sms");

    protected Context context;
    
    public SmsReader(Context context) {
        this.context = context;
    }
    
    /**
     * Zwraca listę wszystkich SMS-ów
     * @param limit limit ilości zwracanych wyników
     * @param offset offest wyników
     * @return lista wszyskich SMS-ów
     */
    public List<SmsMessage> getSmsList(Integer limit, Integer offset){
        return getSmsList(null, null, limit, offset);
    }
    
    /**
     * Zwraca listę wszystkich SMS-ów od podanego momentu
     * @param sinceTimestamp timestamp od którego będą zwracane SMS-y
     * @param limit limit ilości zwracanych wyników
     * @param offset offest wyników
     * @return listę wszystkich SMS-ów od podanego momentu
     */
    public List<SmsMessage> getSmsList(long sinceTimestamp, Integer limit, Integer offset) {
        String[] values = new String[1];
        values[0] = String.valueOf(sinceTimestamp);
        return getSmsList("date > ?", values, limit, offset);
    }
    
    
    protected List<SmsMessage> getSmsList(String whereCondition, String[] whereValues,
            Integer limit, Integer offset){
        List<SmsMessage> resultList = new ArrayList<SmsMessage>();
        String sortOrder = "date ASC";
        if(limit != null && offset != null){
            sortOrder += " LIMIT " + offset.intValue() +"," + limit.intValue();
        } else if(limit != null){
            sortOrder += " LIMIT " + limit.intValue();
        }

        Cursor cursor = context.getContentResolver().query(
                SMS_INBOX_CONTENT_URI,
                new String[] { "_id", "address", "person", "date", "type", "body" },
                whereCondition,
                whereValues,
                sortOrder);
        
        if (cursor != null) {
            // podręczna mapa hashów numerów telefonów
            Map<String, String> numberHashMap = new HashMap<String, String>();
            
            try {
                while(cursor.moveToNext()){
                    long messageId = cursor.getLong(0);
                    String address = cursor.getString(1);
                    long timestamp = cursor.getLong(3);
                    int type = cursor.getInt(4);
                    String body = cursor.getString(5);
                    
                    if(address == null){
                        // to się może zdarzyć, jeżeli użytkownik zacznie pisać SMS-a i nie podając
                        // numeru telefonu wyjdzie z aplikacji - wiadomość zostanie zapisana
                        // jako draft, a numer telefonu będzie NULL
                        address = "";
                    }
                    if(body == null){
                        // na wszelki wypadek
                        body = "";
                    }
                    
                    String number = address;
                    number = MiscUtils.shortenPhoneNumber(number);
                    
                    // numer telefonu przechowujemy w postaci skrótu
                    if(!numberHashMap.containsKey(number)){
                        numberHashMap.put(number, MiscUtils.hashString(number));
                    }
                    String hashedNumber = numberHashMap.get(number);
                    
                    SmsMessage smsMessage = new SmsMessage(messageId, MessageType.forInt(type), 
                            hashedNumber, body, timestamp);
                    resultList.add(smsMessage);
                }
            } finally {
                cursor.close();
            }
        }
        return resultList;
    }

}
